View Javadoc

1   package net.sourceforge.simplegamenet.chess;
2   
3   import java.io.Serializable;
4   
5   public class ChessPlayField implements ChessGridSize, ChessPlayFieldState, ChessPieceType,
6           ChessPieceOwner, Serializable {
7   
8       public static final int[][] DEFAULT_PIECE_TYPE_GRID = {
9           {ROOK, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, ROOK},
10          {KNIGHT, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, KNIGHT},
11          {BISHOP, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, BISHOP},
12          {QUEEN, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, QUEEN},
13          {KING, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, KING},
14          {BISHOP, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, BISHOP},
15          {KNIGHT, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, KNIGHT},
16          {ROOK, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, ROOK}
17      };
18      public static final int[][] DEFAULT_PIECE_OWNER_GRID = {
19          {
20              BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
21              NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
22          },
23          {
24              BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
25              NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
26          },
27          {
28              BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
29              NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
30          },
31          {
32              BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
33              NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
34          },
35          {
36              BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
37              NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
38          },
39          {
40              BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
41              NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
42          },
43          {
44              BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
45              NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
46          },
47          {
48              BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
49              NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
50          }
51      };
52  
53      public static boolean isCheckState(ChessPiece[] checkingPieceGrid,
54                                         int participantsOwnerIndex) {
55          int kingX = -1;
56          int kingY = -1;
57          for (int i = 0; i < checkingPieceGrid.length; i++) {
58              if (checkingPieceGrid[i] != null && checkingPieceGrid[i] instanceof ChessKing
59                      && checkingPieceGrid[i].getParticipantsOwnerIndex()
60                      == participantsOwnerIndex) {
61                  kingX = checkingPieceGrid[i].getX();
62                  kingY = checkingPieceGrid[i].getY();
63                  break;
64              }
65          }
66          for (int i = 0; i < GRID_HEIGHT * GRID_WIDTH; i++) {
67              if (checkingPieceGrid[i] != null
68                      && checkingPieceGrid[i].getParticipantsOwnerIndex() != participantsOwnerIndex
69                      && checkingPieceGrid[i].isMoveAllowed(checkingPieceGrid, kingX, kingY)) {
70                  return true;
71              }
72          }
73          return false;
74      }
75  
76      public static boolean isCheckAfterMoveState(ChessPiece[] checkingPieceGrid,
77                                                  int participantsOwnerIndex) {
78          for (int i = 0; i < checkingPieceGrid.length; i++) {
79              if (checkingPieceGrid[i] != null
80                      && checkingPieceGrid[i].getParticipantsOwnerIndex()
81                      == participantsOwnerIndex) {
82                  for (int j = 0; j < checkingPieceGrid.length; j++) {
83                      if (checkingPieceGrid[i].isMoveAllowed(checkingPieceGrid,
84                              j / GRID_HEIGHT, j % GRID_HEIGHT)) {
85                          ChessPiece[] tempPieceGrid = new ChessPiece[checkingPieceGrid.length];
86                          for (int k = 0; k < tempPieceGrid.length; k++) {
87                              if (checkingPieceGrid[k] != null) {
88                                  tempPieceGrid[k] = (ChessPiece) checkingPieceGrid[k].clone();
89                              }
90                          }
91                          tempPieceGrid[i].doMove(tempPieceGrid,
92                                  j / GRID_HEIGHT, j % GRID_HEIGHT);
93                          if (!isCheckState(tempPieceGrid, participantsOwnerIndex)) {
94                              return false;
95                          }
96                      }
97                  }
98              }
99          }
100         return true;
101     }
102 
103     private Integer[] participantsOrder;
104 
105     private int state = NORMAL_STATE;
106     private boolean waitingForRemiseOfferAnswer = false;
107 
108     private int participantAtTurnIndex = 0;
109 
110     private ChessPiece[] pieceGrid = new ChessPiece[GRID_WIDTH * GRID_HEIGHT];
111 
112     public ChessPlayField(Integer[] participantsOrder) {
113         this.participantsOrder = participantsOrder;
114         for (int i = 0; i < GRID_WIDTH; i++) {
115             for (int j = 0; j < GRID_HEIGHT; j++) {
116                 ChessPiece chessPiece = null;
117                 int participantOwnerIndex = -1;
118                 switch (DEFAULT_PIECE_OWNER_GRID[i][j]) {
119                     case WHITE_OWNER:
120                         participantOwnerIndex = 0;
121                         break;
122                     case BLACK_OWNER:
123                         participantOwnerIndex = 1;
124                         break;
125                 }
126                 switch (DEFAULT_PIECE_TYPE_GRID[i][j]) {
127                     case KING:
128                         chessPiece = new ChessKing(participantOwnerIndex, i, j);
129                         break;
130                     case QUEEN:
131                         chessPiece = new ChessQueen(participantOwnerIndex, i, j);
132                         break;
133                     case BISHOP:
134                         chessPiece = new ChessBishop(participantOwnerIndex, i, j);
135                         break;
136                     case KNIGHT:
137                         chessPiece = new ChessKnight(participantOwnerIndex, i, j);
138                         break;
139                     case ROOK:
140                         chessPiece = new ChessRook(participantOwnerIndex, i, j);
141                         break;
142                     case PAWN:
143                         chessPiece = new ChessPawn(participantOwnerIndex, i, j);
144                         break;
145                 }
146                 pieceGrid[i * GRID_HEIGHT + j] = chessPiece;
147             }
148         }
149     }
150 
151     public Integer getParticipantAtTurnPlayerID() {
152         return participantsOrder[participantAtTurnIndex];
153     }
154 
155     public boolean isMoveAllowed(int sourceX, int sourceY,
156                                  int destinationX, int destinationY, int chosenPieceType) {
157         if (sourceX < 0 || sourceY < 0 || destinationX < 0 || destinationY < 0
158                 || sourceX >= GRID_WIDTH || sourceY >= GRID_HEIGHT
159                 || destinationX >= GRID_WIDTH || destinationY >= GRID_HEIGHT) {
160             return false;
161         }
162         if (isMoveAllowed(sourceX, sourceY, destinationX, destinationY)) {
163             if (isReplaceChoiceNeeded(sourceX, sourceY, destinationX, destinationY)) {
164                 switch (chosenPieceType) {
165                     case QUEEN:
166                         return true;
167                     case BISHOP:
168                         return true;
169                     case KNIGHT:
170                         return true;
171                     case ROOK:
172                         return true;
173                     default:
174                         return false;
175                 }
176             } else {
177                 return true;
178             }
179         } else {
180             return false;
181         }
182     }
183 
184     private boolean isMoveAllowed(int sourceX, int sourceY,
185                                   int destinationX, int destinationY) {
186         if (pieceGrid[sourceX * GRID_HEIGHT + sourceY] == null) {
187             return false;
188         }
189         if (pieceGrid[sourceX * GRID_HEIGHT + sourceY]
190                 .isMoveAllowed(pieceGrid, destinationX, destinationY)) {
191             ChessPiece[] tempPieceGrid = new ChessPiece[pieceGrid.length];
192             for (int i = 0; i < tempPieceGrid.length; i++) {
193                 if (pieceGrid[i] != null) {
194                     tempPieceGrid[i] = (ChessPiece) pieceGrid[i].clone();
195                 }
196             }
197             tempPieceGrid[sourceX * GRID_HEIGHT + sourceY]
198                     .doMove(tempPieceGrid, destinationX, destinationY);
199             return !isCheckState(tempPieceGrid,
200                     tempPieceGrid[destinationX * GRID_HEIGHT + destinationY]
201                     .getParticipantsOwnerIndex());
202         } else {
203             return false;
204         }
205     }
206 
207     public int doMove(int sourceX, int sourceY, int destinationX, int destinationY,
208                       int chosenPieceType) {
209         if (isReplaceChoiceNeeded(sourceX, sourceY, destinationX, destinationY)) {
210             pieceGrid[sourceX * GRID_HEIGHT + sourceY].doMove(pieceGrid,
211                     destinationX, destinationY);
212             switch (chosenPieceType) {
213                 case QUEEN:
214                     pieceGrid[destinationX * GRID_HEIGHT + destinationY]
215                             = new ChessQueen(pieceGrid[destinationX * GRID_HEIGHT + destinationY]
216                             .getParticipantsOwnerIndex(),
217                                     destinationX, destinationY);
218                     break;
219                 case BISHOP:
220                     pieceGrid[destinationX * GRID_HEIGHT + destinationY]
221                             = new ChessBishop(pieceGrid[destinationX * GRID_HEIGHT + destinationY]
222                             .getParticipantsOwnerIndex(),
223                                     destinationX, destinationY);
224                     break;
225                 case KNIGHT:
226                     pieceGrid[destinationX * GRID_HEIGHT + destinationY]
227                             = new ChessKnight(pieceGrid[destinationX * GRID_HEIGHT + destinationY]
228                             .getParticipantsOwnerIndex(),
229                                     destinationX, destinationY);
230                     break;
231                 case ROOK:
232                     pieceGrid[destinationX * GRID_HEIGHT + destinationY]
233                             = new ChessRook(pieceGrid[destinationX * GRID_HEIGHT + destinationY]
234                             .getParticipantsOwnerIndex(),
235                                     destinationX, destinationY);
236                     break;
237             }
238         } else {
239             pieceGrid[sourceX * GRID_HEIGHT + sourceY].doMove(pieceGrid,
240                     destinationX, destinationY);
241         }
242         participantAtTurnIndex = (participantAtTurnIndex + 1) % participantsOrder.length;
243         if (isCheckState(pieceGrid, participantAtTurnIndex)) {
244             if (isCheckAfterMoveState(pieceGrid, participantAtTurnIndex)) {
245                 state = CHECKMATE;
246                 participantAtTurnIndex = (participantAtTurnIndex + 1)
247                         % participantsOrder.length;
248             } else {
249                 state = CHECK;
250             }
251         } else {
252             if (isCheckAfterMoveState(pieceGrid, participantAtTurnIndex)) {
253                 state = STALEMATE;
254                 participantAtTurnIndex = -1;
255             } else {
256                 state = NORMAL_STATE;
257             }
258         }
259         return state;
260     }
261 
262     public void setWaitingForRemiseOfferAnswer() {
263         waitingForRemiseOfferAnswer = true;
264     }
265 
266     public int setRemiseOfferAnswer(boolean remiseOfferAccepted) {
267         waitingForRemiseOfferAnswer = false;
268         if (remiseOfferAccepted) {
269             state = REMISE;
270             participantAtTurnIndex = -1;
271         }
272         return state;
273     }
274 
275     public int yieldGame(Integer playerID) {
276         int participantsIndex = 0;
277         for (int i = 0; i < participantsOrder.length; i++) {
278             if (participantsOrder[i].equals(playerID)) {
279                 participantsIndex = i;
280                 break;
281             }
282         }
283         state = YIELDED;
284         participantAtTurnIndex = (participantsIndex + 1) % participantsOrder.length;
285         return state;
286     }
287 
288     public boolean[][] getMoveSourceAllowedGrid() {
289         boolean[][] moveSourceAllowedGrid = new boolean[GRID_WIDTH][GRID_HEIGHT];
290         for (int i = 0; i < GRID_WIDTH; i++) {
291             for (int j = 0; j < GRID_HEIGHT; j++) {
292                 moveSourceAllowedGrid[i][j] = pieceGrid[i * GRID_HEIGHT + j] != null
293                         && pieceGrid[i * GRID_HEIGHT + j]
294                         .getParticipantsOwnerIndex()
295                         == participantAtTurnIndex;
296             }
297         }
298         return moveSourceAllowedGrid;
299     }
300 
301     public boolean[][] getMoveDestinationAllowedGrid(int sourceX, int sourceY) {
302         boolean[][] moveDestinationAllowedGrid = new boolean[GRID_WIDTH][GRID_HEIGHT];
303         for (int i = 0; i < GRID_HEIGHT; i++) {
304             for (int j = 0; j < GRID_WIDTH; j++) {
305                 moveDestinationAllowedGrid[i][j] = isMoveAllowed(sourceX, sourceY, i, j);
306             }
307         }
308         return moveDestinationAllowedGrid;
309     }
310 
311     public boolean isReplaceChoiceNeeded(int sourceX, int sourceY,
312                                          int destinationX, int destinationY) {
313         return pieceGrid[sourceX * GRID_HEIGHT + sourceY] != null
314                 && pieceGrid[sourceX * GRID_HEIGHT + sourceY] instanceof ChessPawn
315                 && ((ChessPawn) pieceGrid[sourceX * GRID_HEIGHT + sourceY])
316                 .isReplaceChoiceNeeded(destinationX, destinationY);
317     }
318 
319     public int getPieceOwnerSight(Integer clientPlayerID) {
320         if (clientPlayerID.equals(participantsOrder[0])) {
321             return WHITE_OWNER;
322         } else if (clientPlayerID.equals(participantsOrder[1])) {
323             return BLACK_OWNER;
324         }
325         return NO_OWNER;
326     }
327 
328     public int getPlayFieldState() {
329         return state;
330     }
331 
332     public int[][] getPieceTypeGrid() {
333         int[][] pieceTypeGrid = new int[GRID_WIDTH][GRID_HEIGHT];
334         for (int i = 0; i < GRID_WIDTH; i++) {
335             for (int j = 0; j < GRID_HEIGHT; j++) {
336                 if (pieceGrid[i * GRID_HEIGHT + j] == null) {
337                     pieceTypeGrid[i][j] = NO_TYPE;
338                 } else {
339                     pieceTypeGrid[i][j] = pieceGrid[i * GRID_HEIGHT + j].getPieceType();
340                 }
341             }
342         }
343         return pieceTypeGrid;
344     }
345 
346     public int[][] getPieceOwnerGrid() {
347         int[][] pieceOwnerGrid = new int[GRID_WIDTH][GRID_HEIGHT];
348         for (int i = 0; i < GRID_WIDTH; i++) {
349             for (int j = 0; j < GRID_HEIGHT; j++) {
350                 if (pieceGrid[i * GRID_HEIGHT + j] == null) {
351                     pieceOwnerGrid[i][j] = NO_OWNER;
352                 } else {
353                     switch (pieceGrid[i * GRID_HEIGHT + j].getParticipantsOwnerIndex()) {
354                         case 0:
355                             pieceOwnerGrid[i][j] = WHITE_OWNER;
356                             break;
357                         case 1:
358                             pieceOwnerGrid[i][j] = BLACK_OWNER;
359                             break;
360                         default:
361                             pieceOwnerGrid[i][j] = NO_OWNER;
362                             break;
363                     }
364                 }
365             }
366         }
367         return pieceOwnerGrid;
368     }
369 
370     public int getState() {
371         return state;
372     }
373 
374     public ChessPiece[] getPieceGrid() {
375         return pieceGrid;
376     }
377 
378 }